/*
 ------------------------------------------------------------------------------
 Copyright (C) 2009-2011 Eternal Games.

 This file is part of the Eternal Tech source code.

 The Eternal Tech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Eternal Tech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Eternal Tech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// g_ability.cpp - Class abilities
//

// TODO:
// - The basic functions are ready but needs some adjustment for talent, class, ability level etc...


#include "g_local2.h"
#include "g_local.h"


/*
 ==============================================================================

    REGENERATIONS

 ==============================================================================
*/


void G_EnergyRegen ()
{
}

/*
 ==================
 G_HealthRegen
 ==================
*/
void G_HealthRegen (edict_t *ent)
{
	int		nextRegen;

	if (ent->health == ent->max_health)
		return;
	if (ent->deadflag == DEAD_DEAD)
		return;
	if (level.time < ent->client->healthregen_time)
		return;

	ent->health += 5;
	if (ent->health > ent->max_health)
		ent->health = ent->max_health;

	gi.sound(ent, CHAN_ITEM, gi.soundindex("items/n_health.wav"), 1, ATTN_NORM, 0);

	nextRegen = 2;
	ent->client->healthregen_time = level.time + nextRegen;

	gi.dprintf("Health: %i\n", ent->health);
}

void G_ArmorRegen ()
{
}

void G_AmmoRegen ()
{
}

/*
 ==================
 G_Regens
 ==================
*/
void G_Regens (edict_t *ent)
{
	G_EnergyRegen();

	G_HealthRegen(ent);

	G_ArmorRegen();

	G_AmmoRegen();
}


/*
 ==============================================================================

    DRONE ABILITY

 ==============================================================================
*/


/*
 ==================
 G_FindMonsterEntity
 ==================
*/
static edict_t *G_FindMonsterEntity (edict_t *ent)
{
	trace_t trace;
	vec3_t  forward, end;

	AngleVectors(ent->client->v_angle, forward, NULL, NULL);
	VectorMA(ent->s.origin, 8192, forward, end);

	trace = gi.trace(ent->s.origin, NULL, NULL, end, ent, MASK_SHOT);

	return trace.ent;
}

/*
 ==================
 G_SpawnDrone

 TODO: Add drone types, use the monsterTable?
 TODO2: The trace fails at some points
 ==================
*/
static void G_SpawnDrone (edict_t *ent)
{
	edict_t *drone;
	trace_t trace;
	vec3_t  forward;

	drone = G_Spawn();

	VectorSet(drone->s.origin, -9999, -9999, -9999);
	drone->classname = "monster_gladiator";

	drone->Monster.Owner = &ent->Character;
	drone->s.scale = 1;
	drone->Monster.Entity = drone;

	AngleVectors(ent->client->v_angle, forward, NULL, NULL);
	VectorMA(ent->s.origin, 150, forward, drone->s.origin);

	trace = gi.trace(ent->s.origin, drone->mins, drone->mins, drone->s.origin, ent, MASK_SHOT);
	if (trace.fraction < 1.0f)
	{
		Com_Printf("G_SpawnMonster: could not spawn monster\n");

		G_FreeEdict(drone);
	}

	ED_CallSpawn(drone);
}

/*
 ==================
 G_DroneCommand

 TODO: Finish commands
 FIXME: Clean comments?
 ==================
*/
void G_DroneCommand (edict_t *ent, const char *command)
{
	edict_t *monsterEntity, *drone;

	if (gi.argc() != 2)
	{
		Com_Printf("Usage: drone <command>\n");
		return;
	}

	if (!Str_ICompare("select", command))
	{
		// Find a monster entity
		monsterEntity = G_FindMonsterEntity(ent);
		
		if (!monsterEntity || !monsterEntity->Targetable)
			return;   // Not a monster entity

		// Check if the monster entity is a drone
		if ((monsterEntity->svflags & SVF_MONSTER) && Targetables_GetParty(monsterEntity->Targetable) == Targetables_GetParty(ent->Targetable))
		{
			// Unselect the drone
			if (&monsterEntity->Monster == ent->Character.SelectedDrone)
			{
				ent->Character.SelectedDrone->SelectedBy = NULL;
				ent->Character.SelectedDrone = NULL;

				gi.dprintf("Drone is now unselected\n");

				return;
			}

			// Another drone was selected so unselect the current one
			if (ent->Character.SelectedDrone != NULL)
			{
				ent->Character.SelectedDrone->SelectedBy = NULL;
				ent->Character.SelectedDrone = NULL;
			}

			// Make the drone selected
			ent->Character.SelectedDrone = &monsterEntity->Monster;
			ent->Character.SelectedDrone->SelectedBy = &ent->Character;

			gi.dprintf("Drone is now selected\n");
		}

		return;
	}
	else if (!Str_ICompare("remove", command))
	{
		if (ent->Character.SelectedDrone == NULL)
			return;

		// Get the drone
		drone = ent->Character.SelectedDrone->Entity;

		// Remove it from the list
		Targetables_Remove(drone);

		// Make it unselected
		if (ent->Character.SelectedDrone->SelectedBy)
			ent->Character.SelectedDrone = NULL;

		// Free it
		G_FreeEdict(drone);
		ent->Character.SelectedDrone = NULL;

		return;
	}
	else if (!Str_ICompare("move", command))
	{
		return;
	}
	else if (!Str_ICompare("stop", command))
	{
		return;
	}
	else if (!Str_ICompare("standGround", command))
	{
		if (ent->Character.SelectedDrone == NULL)
			return;

		ent->Character.SelectedDrone->HasMoveTo = false;
		ent->Character.SelectedDrone->Entity->monsterinfo.aiflags ^= AI_STAND_GROUND;
		ent->Character.SelectedDrone->Entity->monsterinfo.stand(ent->Character.SelectedDrone->Entity);

		gi.dprintf("Drone is now standing ground\n");

		return;
	}

	// Spawn it
	G_SpawnDrone(ent);
}